contents

Git은 작거나 매우 큰 프로젝트를 빠르고 효율적으로 처리하도록 설계된 무료 오픈소스 **분산 버전 관리 시스템(DVCS)**입니다. 2005년 리눅스 커널을 만든 리누스 토르발스가 개발했으며, 현재는 소스 코드 관리를 위한 전 세계적인 표준이 되었습니다.


Git이 해결하는 문제 (존재 이유)

Git 이전에는 개발자들이 코드 변경 사항을 관리하는 데 상당한 어려움을 겪었습니다.

Git은 분산 시스템이라는 특징으로 이 문제를 해결했습니다. 저장소를 복제(clone)하면 파일의 최신 버전만 가져오는 것이 아니라, 프로젝트의 전체 히스토리를 로컬 머신에 가져옵니다.


핵심 개념: Git의 사고방식 🧠

Git을 제대로 이해하려면 다른 시스템과는 다른 Git의 기본 철학을 이해해야 합니다.

1. 차이가 아닌 스냅샷

대부분의 다른 버전 관리 시스템은 정보를 파일 기반의 변경 사항 목록(델타 또는 diff)으로 저장합니다. Git은 데이터를 다르게 생각합니다. 커밋(commit)(프로젝트 상태를 저장)할 때마다 Git은 기본적으로 그 순간의 모든 파일에 대한 사진, 즉 스냅샷을 찍고 그 스냅샷에 대한 참조를 저장합니다. 효율성을 위해 파일이 변경되지 않았다면 Git은 파일을 다시 저장하지 않고, 이미 저장된 이전의 동일한 파일에 대한 링크만 저장합니다.

2. 세 가지 상태

이는 일상적인 사용에서 가장 중요한 개념입니다. Git에는 파일이 존재할 수 있는 세 가지 주요 상태가 있습니다.

비유: 당신이 전시회를 준비하는 사진작가라고 상상해 보세요.

3. 분산된 특징

모든 개발자의 작업 복사본은 완전한 기능을 갖춘 리포지토리입니다. 이는 완전히 오프라인 상태에서도 새로운 버전을 커밋하고, 히스토리를 보고, 브랜치를 생성할 수 있다는 의미입니다. 다른 사람에게 변경 사항을 푸시하거나 다른 사람의 변경 사항을 풀(pull)할 때만 원격 서버에 연결하면 됩니다. 이는 Git을 엄청나게 빠르고 유연하게 만듭니다.


기본 워크플로우 및 필수 명령어

기본적인 Git 워크플로우는 세 가지 상태를 따릅니다.

  1. 작업 디렉터리에서 파일을 수정합니다.

  2. 다음 커밋에 포함할 변경 사항을 선택적으로 골라 스테이징 영역에 추가합니다.

  3. 커밋을 수행하여 스테이징 영역에 있는 파일들의 스냅샷을 **Git 디렉터리(리포지토리)**에 영구적으로 저장합니다.

이 워크플로우에 해당하는 명령어는 다음과 같습니다.


브랜치와 병합: Git의 슈퍼파워 🌿

이것은 Git의 가장 중요한 기능이라고 할 수 있습니다.

브랜치란?

Git의 브랜치는 단순히 커밋을 가리키는 가볍고 이동 가능한 포인터입니다. 코드베이스의 복사본이 아닙니다. 새 브랜치를 만들 때 Git은 단지 새 포인터를 생성할 뿐입니다. 이 덕분에 프로젝트 크기에 상관없이 브랜치를 만들고 전환하는 것이 거의 즉각적으로 이루어집니다.

왜 브랜치를 사용하는가?

브랜치를 사용하면 주 개발 라인(main 또는 master)에서 벗어나 새로운 기능, 버그 수정 또는 실험을 독립적으로 진행할 수 있습니다. 작업이 성공적이지 않으면 브랜치를 간단히 버릴 수 있고, 성공적이면 주 브랜치로 **병합(merge)**할 수 있습니다.

필수 브랜치 명령어


원격 리포지토리 작업 🤝

협업을 하려면 다른 사람들과 작업을 동기화해야 합니다. 이는 원격 리포지토리(주로 GitHub, GitLab, Bitbucket과 같은 서비스에서 호스팅됨)와 상호 작용하여 수행됩니다.

일반적인 워크플로우

팀은 이러한 핵심 기능을 사용하여 워크플로우를 구축합니다. 가장 일반적인 것은 **기능 브랜치 워크플로우(Feature Branch Workflow)**입니다.

  1. main 브랜치는 항상 안정적이고 배포 가능한 상태로 유지합니다.

  2. 새로운 작업(기능 또는 버그 수정)을 하려면 main에서 새 브랜치를 만듭니다(예: feature/add-login-page).

  3. 이 브랜치에 작업을 커밋합니다.

  4. 기능이 완성되면 GitHub와 같은 플랫폼에서 "풀 리퀘스트(Pull Request)"(또는 "Merge Request")를 엽니다.

  5. 팀원들이 코드를 검토하고 승인되면, 기능 브랜치는 다시 main으로 병합됩니다.

결론적으로, Git은 현대 소프트웨어 개발을 위한 견고한 기반을 제공하는 강력하고 다재다능한 도구입니다. 그 속도, 분산된 특징, 강력한 브랜치 기능 덕분에 코드를 작성하는 모든 사람에게 필수적인 기술이 되었습니다.


프로그래밍 및 알고리즘 관점에서 본 Git의 설계는 단순함과 효율성의 정수라고 할 수 있습니다. Git이 속도와 낮은 저장 공간 요구사항을 달성한 것은 복잡한 알고리즘 하나가 아니라, 영리하고 단순한 아이디어들의 조합 덕분입니다.

Git이 어떻게 만들어졌는지에 프로그래밍 관점에서 간단하게 알아보겠습니다.


프로그래밍 언어

Git은 주로 C언어로 작성되었습니다. 리누스 토르발스가 C를 선택한 데에는 몇 가지 핵심적인 이유가 있습니다.

핵심 기능은 C로 작성되었지만, 많은 상위 수준의 "porcelain" 명령어들은 초기에 셸 스크립트로 작성되었습니다. 이를 통해 빠른 프로토타이핑과 개발이 가능했습니다. 시간이 지나면서 이들 중 다수는 더 나은 성능과 플랫폼 간 일관성을 위해 C로 재작성되었습니다.


핵심 데이터 모델: 속도와 단순성의 기반

Git의 기초는 믿을 수 없을 정도로 단순한 키-값(key-value) 데이터 저장소입니다. Git의 핵심에서 모든 것은 객체(object) 이며, 전체 시스템은 단 네 가지 객체 유형(블롭, 트리, 커밋, 태그) 위에 구축됩니다. 이 시스템의 핵심은 객체가 저장되고 참조되는 방식에 있습니다.

1. 콘텐츠 주소 지정 방식 저장소 (비밀 병기)

이것이 Git 설계의 가장 뛰어난 부분이자 대부분의 장점이 나오는 원천입니다. Git이 어떤 콘텐츠(파일 데이터, 디렉터리 구조, 커밋 등)를 저장할 때, 무작위 이름을 부여하지 않습니다. 대신 다음과 같이 작동합니다.

  1. 객체 유형을 식별하는 작은 헤더를 추가합니다(예: "blob").

  2. 이 헤더와 콘텐츠를 SHA-1 해싱 알고리즘에 통과시킵니다.

  3. 결과로 나오는 40자리의 16진수 문자열이 바로 그 객체의 이름이자 가 됩니다.

이러한 콘텐츠 주소 지정 방식은 엄청난 이점을 가집니다.

2. 단순한 객체 그래프

이 객체들은 단순하고 불변(immutable, 절대 변하지 않음)이기 때문에 시스템을 이해하고 작업을 수행하는 것이 매우 간단해집니다.


데이터 저장 효율성: 팩파일(Packfiles)

.git/objects 디렉터리에 수백만 개의 작은 객체 파일("느슨한 객체")을 두는 것은 대부분의 파일 시스템에서 매우 비효율적입니다. 이 문제를 해결하기 위해 Git은 팩파일을 사용합니다.

주기적으로(또는 push/pull 시) Git은 많은 느슨한 객체들을 팩파일(.pack) 이라는 고도로 압축된 단일 파일로 묶습니다. 이는 ZIP 파일을 만드는 것과 비슷합니다.

하지만 훨씬 더 영리한 일을 합니다: 델타 압축(Delta Compression).

패킹 과정에서 Git은 유사한 파일들을 찾습니다(예: 동일한 소스 코드 파일의 두 버전). 두 파일 전체를 저장하는 대신, 한 버전은 완전한 "베이스" 객체로 저장하고 다른 버전은 베이스와의 차이점, 즉 델타만 저장합니다.

이것이 Git이 점진적으로 변경되는 텍스트 기반 파일을 매우 효율적으로 저장하는 이유입니다. Git은 사용자 모델 관점에서는 스냅샷으로 생각하지만, 저장 모델 관점에서는 델타를 사용합니다. (전자는 이해하기 쉽고, 후자는 효율적입니다.)

이 큰 팩파일 안에서도 객체를 빠르게 찾을 수 있도록, Git은 객체의 SHA-1 해시를 팩파일 내의 바이트 오프셋에 매핑하는 인덱스 파일(.idx)도 함께 생성합니다.


브랜칭과 병합이 빠른 이유

요약하자면, Git의 천재성은 단순함에 있습니다. SHA-1 해싱을 이용한 콘텐츠 주소 지정 방식의 키-값 저장소, 단순하고 불변인 객체 그래프, 그리고 델타 압축된 팩파일과 같은 영리한 저장 최적화 등 몇 가지 근본적이고 강력한 프로그래밍 개념 위에 구축되었습니다. 이 기반이 바로 Git을 그토록 빠르고, 효율적이며, 신뢰할 수 있게 만드는 것입니다.

references